#pragma once

#include <vector>
#include <tr1/memory>
#include "ini_io.hpp"


QFL_NAMESPACE_BEGIN
namespace text
{



	template < typename _CharT, typename _Traits >
	class ini_tree
	{
	public:
		typedef std::basic_string<_CharT,_Traits> string_type;
		typedef ini_io<_CharT,_Traits> io_type;
		typedef typename io_type::index_pair index_pair;

	public:
		// class for key value node
		class key_node
		{
		public:
			int line_index;
			string_type name;
			index_pair value_index;

			key_node(int n, const string_type& key, index_pair& value)
				: line_index(n), name(key), value_index(value)
			{
			}
		};

		// class for section node
		class section_node
		{
		public:
			typedef std::vector< std::tr1::shared_ptr<key_node> > key_vector;

		public:
			int line_index;
			string_type name;
			key_vector keys;

			section_node(int n, const string_type& section)
				: line_index(n), name(section)
			{
			}
			key_node* find(const string_type& key_name)
			{
				key_vector::iterator it;
				for ( it=keys.begin(); it!=keys.end(); ++it )
				{
					if ((*it)->name==key_name) break;
				}
				return (it==keys.end())? 0 : (*it).get();
			}
		};


	// operator of class ini tree
	public:
		ini_tree(const io_type& io)
		{
			//todo: 
			index_pair ip;
			section_node *section;
			int n = (int)io.line_count();
			for ( int i=0; i<n; ++i)
			{
				ip = io.get_section(i);
				if (ip.first!=ip.second)
				{
					section = new section_node(i,io.get_string(i,ip));
					append(std::tr1::shared_ptr<section_node>(section));
				}
				else if (section)
				{
					ip = io.get_key(i);
					string_type key_name = io.get_string(i,ip);
					if (ip.first!=ip.second)
					{
						ip = io.get_value(i);
						key_node* key = new key_node(i-section->line_index,key_name,ip);
						section->keys.push_back(std::tr1::shared_ptr<key_node>(key));
					}
				}
			}
		}
		void append(std::tr1::shared_ptr<section_node>& section)
		{
			sections_.push_back(section);
		}
		section_node* find(const string_type& section_name)
		{
			std::vector< std::tr1::shared_ptr<section_node> >::iterator it;
			for ( it=sections_.begin(); it!=sections_.end(); ++it )
			{
				if ((*it)->name==section_name) break;
			}
			return (it==sections_.end())? 0 : (*it).get();
		}
		void update_index_for_insert_one_line(int inserted_line_index)
		{
			std::vector< std::tr1::shared_ptr<section_node> >::iterator it;
			for ( it=sections_.begin(); it!=sections_.end(); ++it )
			{
				if ((*it)->line_index>=inserted_line_index)
				{
					++((*it)->line_index);
				}
			}
		}

	private:
		std::vector< std::tr1::shared_ptr<section_node> > sections_;
	};




}
QFL_NAMESPACE_END
